package code

import (
	"bytes"
	"encoding/binary"
	"fmt"

	"GoNet/core"

	"code.google.com/p/goprotobuf/proto"
)

type ServerDecodeEncode struct {
}

//解码
func (decodeEncode *ServerDecodeEncode) Decode(left []byte, serverEngin *core.ServerEngin, session *core.Session) (leftResult []byte, message *core.Message, err error) {
	avalibleRead := len(left)
	if avalibleRead < 4 {
		return left, nil, nil
	}

	b_buf := bytes.NewBuffer(left)
	var msgLenth int32
	err = binary.Read(b_buf, binary.BigEndian, &msgLenth)
	if err != nil {

		fmt.Println("解码错误可用长度", avalibleRead)
		return
	}
	//fmt.Println("有粘包", avalibleRead, msgLenth)

	//判断长度
	if avalibleRead < int(msgLenth+4) {
		return left, nil, nil
	}

	message = new(core.Message)
	msgType := new(int16)
	//读取Type
	err = binary.Read(b_buf, binary.BigEndian, msgType)
	message.Type = (int32)(*msgType)
	if err != nil {
		return
	}
	//读取消息体break

	message.ByteBody = left[6 : msgLenth+4]

	//解析消息体成pb等
	temp := serverEngin.HandlerBodyManager.GetBody(&message.Type)
	body := temp.(proto.Message)

	err = proto.Unmarshal(message.ByteBody, body)
	if err != nil {
		return
	}
	message.Session = session
	message.Body = body

	return left[msgLenth+4:], message, nil

}

//编码
func (decodeEncode *ServerDecodeEncode) Encode(message *core.Message) ([]byte, error) {
	//将消息体转成byte
	bodyBytes, err := proto.Marshal(message.Body)

	if err != nil {
		return nil, err
	}
	message.ByteBody = bodyBytes

	result := make([]byte, 0)

	b_buf := bytes.NewBuffer(result)
	msgLenth := len(message.ByteBody) + 2
	//写入长度
	if err := binary.Write(b_buf, binary.BigEndian, int32(msgLenth)); err != nil {
		return nil, err
	}
	//写入id
	msgType := (int16)(message.Type)
	if err := binary.Write(b_buf, binary.BigEndian, msgType); err != nil {
		return nil, err

	}
	//写入消息体
	if err := binary.Write(b_buf, binary.BigEndian, message.ByteBody); err != nil {
		return nil, err
	}

	return b_buf.Bytes(), nil
}
